package br.com.afi.util.managerEmail;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;

import javax.mail.internet.InternetAddress;

import br.com.afi.util.log.Logger;


/**
 * Thread para envio de vários e-mails.
 * 
 * @author André de Fontana Ignacio
 * @version 1.0
 */
public class ManagerEmailThread extends Observable implements Runnable
{
	private static final Logger log = Logger.getLogger( ManagerEmailThread.class );
	private ManagerEmail managerEmail;
	private Thread blinker;
	private List<Email> emails;
	private int interval;
	private int sendedEmailsCount;
	private List<String> emailsNaoEnviados;

	/**
	 * Construtor
	 * 
	 * @param managerEmail Gerenciador de e-mails
	 * @param interval Intervalo entre o envio de e-mail.
	 */
	public ManagerEmailThread( ManagerEmail managerEmail, int interval )
	{
		this.interval = interval;
		this.managerEmail = managerEmail;
	}

	public void start()
	{
		blinker = new Thread( this );
		blinker.start();
		emailsNaoEnviados = new LinkedList<String>();
	}

	public void stop()
	{
		emails = null;
		blinker = null;
	}

	public void run()
	{
		log.debug( "Thread para enviar e-mails iniciada" );
		final Thread thisThread = Thread.currentThread();
		while ( blinker == thisThread )
		{
			try
			{
				Thread.sleep( interval );
			}
			catch ( InterruptedException e )
			{
				final EmailRuntimeException exception = new EmailRuntimeException( "Erro no sleep da Thread", e );
				log.error( exception.getMessage(), exception );
				throw exception;
			}
			if ( emails != null )
			{
				for ( Iterator<Email> it = this.emails.iterator(); it.hasNext(); )
				{
					final Email email = it.next();
					try
					{
						managerEmail.sendEmail( email );
						this.setChanged();
						this.notifyObservers( "ENVIADO" );
					}
					catch ( EmailException e )
					{
						for ( Iterator<InternetAddress> i = email.getDestinatarios().iterator(); i.hasNext(); )
						{
							final InternetAddress internetAddress = i.next();
							this.emailsNaoEnviados.add( internetAddress.getAddress() );
						}
						this.setChanged();
						this.notifyObservers( "ENVIADO" );
					}
					catch ( AuthenticationFailedException ea )
					{
						this.setChanged();
						this.notifyObservers( "ERRO" );
						throw new EmailRuntimeException( ea.getMessage(), ea );
					}
					catch ( Exception ex )
					{
						this.setChanged();
						this.notifyObservers( "ERRO" );
						final EmailRuntimeException exception = new EmailRuntimeException( "Erro ao enviar e-mail " + email.getAssunto(), ex );
						log.error( exception.getMessage(), exception );
						throw exception;
					}
					finally
					{
						emails = null;
					}
				}
				this.setChanged();

				if ( getEmailsNaoEnviados().isEmpty() )
				{
					this.notifyObservers( "OK" );
				}
				else
				{
					this.notifyObservers( "QUASEOK" );
				}
			}
			log.debug( "Thread para enviar e-mails finalizada" );
		}
	}

	/**
	 * Envia os e-mails informados.
	 * 
	 * @param emails E-mail
	 */
	public void sendEmails( List<Email> emails )
	{
		this.emails = emails;
	}

	public int getSendedEmailsCount()
	{
		return this.sendedEmailsCount;
	}

	public List<String> getEmailsNaoEnviados()
	{
		return emailsNaoEnviados;
	}

	public void setEmailsNaoEnviados( List<String> emailsNaoEnviados )
	{
		this.emailsNaoEnviados = emailsNaoEnviados;
	}

}
